package com.ft.service.impl;

import com.ft.domain.WeiXinPayToUniapp;
import com.ft.service.WxPayService;
import com.ft.utils.Result;
import com.ft.utils.WxPayUtils;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.xml.sax.SAXException;

import javax.net.ssl.SSLContext;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

/**
 * @Author: ft
 * @Date: 2022/10/09/15:41
 * @Description:
 */
@Service
public class WxPayServiceImpl implements WxPayService {
    /**
     *
     * @param url 请求地址
     * @param jsonString 请求数据
     * @return 0 失败，1成功
     * @throws Exception
     */
    @Override
    public WeiXinPayToUniapp wxPay(String url, String jsonString) throws Exception {
        WeiXinPayToUniapp weiXinPayToUniapp = null;
        //1.通过定制创建CloseableHttpClient对象，它相当于就是打开一个浏览器
        Registry<ConnectionSocketFactory> rer = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                //通过自定义方法构建
                .register("https",trustHttpCertificates())
                .build();
        //创建一个ConnectionManager对象
        PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(rer);
        //定制closeableHttpClient对象
        HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(pool);
        //配置好Httpclient之后，通过build()方法来创建HttpClient对象
        CloseableHttpClient aDefault = httpClientBuilder.build();
        //3.创建发送post方法的HttpPost对象
        HttpPost request = new HttpPost(url);
        //添加请求参数
        // 通过new StringEntity()，可将Content-Type设置为text/plain类型
        request.setEntity(new StringEntity(jsonString,"UTF-8"));
        //对请求进行设置
        RequestConfig.Builder customReqConf = RequestConfig.custom();
        //设置链接超时时间
        customReqConf.setConnectTimeout(5000);
        //读取超时，表示从请求的网址出获取数据超时的时间
        customReqConf.setSocketTimeout(3000);
        request.setConfig(customReqConf.build());
        //设置请求头
        request.setHeader("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36");
        //4.创建响应对象
        CloseableHttpResponse response = null ;
        try {
            //执行
            response = aDefault.execute(request);
            //5.获取响应结果
            HttpEntity ey = response.getEntity();
            //6.通过自带的EntityUtils工具类对ey处理
            String s = EntityUtils.toString(ey,"utf-8");
            Map<String, String> mapFromXML = WxPayUtils.getMapFromXML(s);
            weiXinPayToUniapp = WxPayUtils.wxReturn(mapFromXML);
            //确保流关闭
            EntityUtils.consume(ey);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            if (aDefault != null) {
                try {
                    aDefault.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return weiXinPayToUniapp;
    }

    /**
     * 微信提现
     * @param url
     * @param xml
     * @return
     */
    public int wxtx(String url,String xml) throws Exception{
        //获取证书地址
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        String filepath = "D:\\web\\吉利校园帮\\glb\\后端\\src\\main\\resources\\static\\";
        System.out.println("filepath->"+filepath);
        FileInputStream instream = new FileInputStream(filepath+"apiclient_cert.p12");
        try {
            keyStore.load(instream, "1628729033".toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }
        //设置证书
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, "1628729033".toCharArray())//这里也是写密码的
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();

        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(xml, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                Map<String, String> mapFromXML = WxPayUtils.getMapFromXML(jsonStr);
                System.out.println("请求的结果是:"+mapFromXML);
                String rs = mapFromXML.get("result_code");
                if(rs != null & rs.equals("SUCCESS")){
                    return 1;
                }
                return 0;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
    /**
     * 微信退款
     * @param url
     * @param jsonString
     * @return
     * @throws Exception
     */
    @Override
    public int wxTk(String url, String jsonString) throws Exception {
        //获取证书地址
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        String filepath = "D:\\web\\吉利校园帮\\glb\\后端\\src\\main\\resources\\static\\";
        System.out.println("filepath->"+filepath);
        FileInputStream instream = new FileInputStream(filepath+"apiclient_cert.p12");
        try {
            keyStore.load(instream, "1628729033".toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }
        //设置证书
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, "1628729033".toCharArray())//这里也是写密码的
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(jsonString, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                Map<String, String> mapFromXML = WxPayUtils.getMapFromXML(jsonStr);
                String rs = mapFromXML.get("result_code");
                System.out.println("请求的结果是:"+rs);
                if(rs != null & rs.equals("SUCCESS")){
                    return 1;
                }
                return 0;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }

    }

    /**
     * 查询微信退款情况
     * @param url
     * @param jsonString
     * @return
     */
    public int wxtyCx(String url, String jsonString) throws Exception {
        int returnRe = 0;
        //获取证书地址
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        //1.通过定制创建CloseableHttpClient对象，它相当于就是打开一个浏览器
        Registry<ConnectionSocketFactory> rer = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                //通过自定义方法构建
                .register("https",trustHttpCertificates())
                .build();
        //创建一个ConnectionManager对象
        PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(rer);
        //定制closeableHttpClient对象
        HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(pool);
        //配置好Httpclient之后，通过build()方法来创建HttpClient对象
        CloseableHttpClient aDefault = httpClientBuilder.build();
        //3.创建发送post方法的HttpPost对象
        HttpPost request = new HttpPost(url);
        //添加请求参数
        // 通过new StringEntity()，可将Content-Type设置为text/plain类型
        request.setEntity(new StringEntity(jsonString,"UTF-8"));
        //对请求进行设置
        RequestConfig.Builder customReqConf = RequestConfig.custom();
        //设置链接超时时间
        customReqConf.setConnectTimeout(5000);
        //读取超时，表示从请求的网址出获取数据超时的时间
        customReqConf.setSocketTimeout(3000);
        request.setConfig(customReqConf.build());
        //设置请求头
        request.setHeader("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36");
        //4.创建响应对象
        CloseableHttpResponse response = null ;
        try {
            //执行
            response = aDefault.execute(request);
            //5.获取响应结果
            HttpEntity ey = response.getEntity();
            //6.通过自带的EntityUtils工具类对ey处理
            String s = EntityUtils.toString(ey,"utf-8");
            Map<String, String> mapFromXML = WxPayUtils.getMapFromXML(s);
            System.out.println(mapFromXML);
            String rs = mapFromXML.get("result_code");
            if(rs != null & rs.equals("SUCCESS")){
                return 1;
            }
            //确保流关闭
            EntityUtils.consume(ey);
            return 0;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (aDefault != null) {
                try {
                    aDefault.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return returnRe;
    }
    /**
     * 创建ssl连接
     * @return
     * @throws Exception
     */
    private ConnectionSocketFactory trustHttpCertificates() throws Exception {
        //创建SSLContext对象
        SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
        //加载下信任的证书
        sslContextBuilder.loadTrustMaterial(null, new TrustStrategy() {
            //判断是否信任url，直接返回true信任
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                return true;
            }
        });
        //设置证书类型
        SSLContext sslContext = sslContextBuilder.build();
        //第一个参数数ssl对象，第二个是协议数组
        SSLConnectionSocketFactory sslfy = new SSLConnectionSocketFactory(sslContext,
                new String[]{"SSLv2Hello","SSLv3","TLSv1","TLSv1.1","TLSv1.2"}
                ,null, NoopHostnameVerifier.INSTANCE);
        return sslfy;
    }

}
